研究生和大學生不同,跟著指導的教授有著獨立的研究室,以滯留時間來看,可說是研究生的第二個家。
「吶,小唯心,最近的學生是不是太死背考古題了啊。」某個教授閒來沒事,和自己的研究生發牢騷。
「誰叫教授們為求省事,使用題庫呢,要不然這次改出新題?」唯心一邊整理數據,一邊淡淡回應。
「咦?麻煩?只要確認學生能按要求寫出合格的程式就好了吧。」翁玉慵懶地玩弄自己的頭髮。
「恕我直言,教授講解的尾遞迴
也不知道有多少學生聽懂,說不定連根本的遞迴
也沒弄清楚。」
翁玉疑惑地轉過頭。「不是吧?遞迴
就是函式
在執行過程裡又呼叫自己,這個也不懂的話,現在的學生真的沒問題嗎?」
「教授妳忘記這次的選課開放新生和外系了嗎?」唯心善意提醒。
「難怪這次教室裡的女孩子比以往多。那為了讓他們明白,也許放些實際例子會比較容易理解吧。現在的高中數學有哪些可以用的例子?」
唯心回想了一下,答道:「費氏數列和階乘吧?」
「那就選階乘好了,費氏數列要呼叫自己兩次,還要數位置,比較難懂吧?」翁玉戳著唯心養的仙人掌,仙人掌的軟刺觸感甚得她心。
fun 費氏數列(n: Int): Int {
return if (n < 2) { n }
else 費氏數列(n - 1) + 費氏數列(n - 2)
}
唯心迅速救走仙人掌盆栽。「也因為呼叫多次,改寫成尾遞迴
的優勢才明顯啊。毀滅性的Stack Overflow Error
不就是因為遞迴
呼叫產生的堆疊太多,還沒回收回來就爆掉了。」唯心頓了一下。「說起來堆疊是在資料結構課程的範圍,如果教授妳要推廣尾遞迴
,那就要讓他們認識堆疊了。」
「要從那裡開始嗎⋯⋯」翁玉無語。
唯心聯想到她和詩憶的補課方式,於是提議:「或許可以說的籠統一點,比如說,每次呼叫函式都會佔據一單位記憶體,當函式執行完才能回收記憶體,所以在執行期間呼叫多個自己的遞迴
就會佔據大量記憶體,最後記憶體滿了程式就掛了。尾遞迴
算是先和程式約好每次最多只能呼叫一次自己,也不能用到其他資源,所以程式能準備重複利用記憶體的機制。」
fun 階乘(n: Int): Int {
return if (n < 2) { n }
else n * 階乘(n - 1)//因為還帶了 n * 所以只是普通的遞迴
}
tailrec fun 階乘尾遞迴(n: Int, tail: Int = 1): Int {
return if (n < 2) { tail }
else 階乘尾遞迴(n - 1, n * tail)
}
「是呀,也不是所有程式語言都能支援尾遞迴
,Java8就不行。說起來小唯心怎麼知道有同學不懂尾遞迴
?」翁玉突然想到這個問題。
「因為有不少同學拿著程式碼來問我他寫的是不是尾遞迴
呀,呵呵。」對面傳來有點陰森的笑聲。「我和他們說,在函式前面加上tailrec
執行看看,IDE發現不對勁就會發警告。」
「嗯,很好的方法。對了,像之前一樣讓學生來這裡找妳也可以唷。」翁玉話才說完,感覺室內溫度立即下降了幾度。「⋯⋯我有事先走了,下次見唷小唯心。」不能再待在這間越發散發危險氣息的研究室哩。